#pragma semicolon 1
#pragma newdecls required

#include <sourcemod>
#include <sdkhooks>

// 伤害类型宏定义（防重定义）
#if !defined DMG_FALL
	#define DMG_FALL       (1 << 5)   // 32 - 坠落伤害
#endif
#if !defined DMG_BURN
	#define DMG_BURN      (1 << 3)   // 8  - 火焰伤害
#endif
#if !defined DMG_BLAST
	#define DMG_BLAST     (1 << 6)   // 64 - 爆炸伤害
#endif

public Plugin myinfo = 
{
	name = "l4d2_incapacitated_damage_blocker",
	author = "豆瓣酱な",
	description = "特感,女巫,小僵尸,无法对倒地或挂边的玩家造成伤害",
	version = "3.0",
	url = "https://gitee.com/sweet-and-sour-bombs/adfvsdsd"
};

public void OnPluginStart()
{
	for (int i = 1; i <= MaxClients; i++)
	{
		if (IsClientInGame(i))
		{
			SDKHook(i, SDKHook_OnTakeDamage, OnTakeDamage);
		}
	}
}

public void OnClientPutInServer(int client)
{
	SDKHook(client, SDKHook_OnTakeDamage, OnTakeDamage);
}

public Action OnTakeDamage(int victim, int &attacker, int &inflictor, float &damage, int &damagetype)
{
	if( victim > 0 && IsClientConnected(victim) && IsClientInGame(victim) && GetClientTeam(victim) == 3 )
	{
		return Plugin_Continue;
	}
	
	if (!IsIncapacitated(victim))
	{
		return Plugin_Continue;
	}

	if (IsPlayerFullySubmerged(victim))
	{
		return Plugin_Continue;
	}
	
	if (damagetype & (DMG_FALL | DMG_BURN | DMG_BLAST))
	{
		return Plugin_Continue;
	}

	damage = 0.0;
	return Plugin_Handled;
}

bool IsIncapacitated(int client)
{
	return view_as<bool>(GetEntProp(client, Prop_Send, "m_isIncapacitated"));
}

/**
 * 判断玩家是否完全浸没（头部在水下）
 * @param client 玩家索引
 * @return true=完全浸没，false=未浸没或部分浸没
 */
bool IsPlayerFullySubmerged(int client)
{
	if (client < 1 || client > MaxClients || !IsClientInGame(client) || !IsPlayerAlive(client))
	{
		return false;
	}
    
	// m_nWaterLevel 取值：
	// 0 = 无水 | 1 = 脚部浸水 | 2 = 腰部浸水 | 3 = 头部浸没
	return (GetEntProp(client, Prop_Data, "m_nWaterLevel") >= 3);
}
